package com.locki.execDDL.service;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.FutureTask;

public class ExecDDL {
	private String dsPath;
	private String scriptPath;
	private String logPath;
	// 数据库驱动
	public static final String driver = "com.ibm.db2.jcc.DB2Driver";
	// 保存数据连接
	private static List<DataSource> dsList = new ArrayList<DataSource>();
	// 保存需要执行的DDL文件
	private List<String> files = new ArrayList<String>();
	// 保存需要执行的DDL
	private static Map<String, String> ddlSql = new HashMap<String, String>();
	// 记录日志,全局
	private static FileWriter logfwTotal = null;

	public ExecDDL(String dsPath, String scriptPath, String logPath) throws IOException {
		dsList.clear();
		files.clear();
		ddlSql.clear();
		
		this.dsPath = dsPath;
		this.scriptPath = scriptPath;
		this.logPath = logPath;

		File log = new File(this.logPath + "/info.log");
		if (log.exists()) {
			log.delete();
			log.createNewFile();
		}
		logfwTotal = new FileWriter(log);
	}

	public void startExec() {
		try {
			//String path = "I:\\工作文件夹\\svn\\01_文档\\04_设计\\BKR\\Procedures\\数据质量\\省局数据抽取\\java\\single\\bak";
			File file = new File(this.scriptPath);
			if (!file.exists() && !file.isDirectory()) {
				throw new Exception("脚本目录错误！！！");
			}

			writeTotalLog("第一步：获取需要执行的脚本", null);
			preScripts(file);
			writeTotalLog("\n第二步：获取有效的数据源", null);
			preDatasources();
			writeTotalLog("\n第三步：缓存所有脚本SQL", null);
			preDDLSqls();
			writeTotalLog("\n第四步：启动线程执行脚本", null);
			
			List<FutureTask<String>> threads = new ArrayList<FutureTask<String>>();
			for(DataSource ds :dsList){
				Run run = new Run();
				run.setPath(logPath);
				run.setDdlSql(ddlSql);
				run.setDs(ds);
				FutureTask<String> task = new FutureTask<String>(run);
				Thread t = new Thread(task);
				t.start();
				threads.add(task);
			}
			
			while(!threads.isEmpty()){
				Iterator<FutureTask<String>> it = threads.iterator();
				while(it.hasNext()){
					FutureTask<String> task = it.next();
					if(task.isDone()){
						it.remove();
					}
				}
				Thread.sleep(1000);
			}
			writeTotalLog("\n完成：所有线程结束", null);
			destory(logfwTotal);
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 记录日志
	 * 
	 * @param msg
	 * @param e
	 */
	public static synchronized void writeTotalLog(String msg, Exception ex) {
		try {
			logfwTotal.write(msg);
			logfwTotal.write("\n");
			logfwTotal.flush();

			if (ex != null) {
				logfwTotal.write(pullException(ex));
				logfwTotal.write("\n");
				logfwTotal.flush();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	/**
	 * 迭代获取所有脚本文件
	 * 
	 * @param file
	 * @throws Exception
	 */
	public void preScripts(File file) {
		if (file.isFile()) {
			if (file.getName().toUpperCase().endsWith("SQL")) {
				files.add(file.getPath());
				writeTotalLog("发现脚本" + file.getAbsolutePath(), null);
			}
		} else {
			File[] files = file.listFiles();
			for (File f : files) {
				preScripts(f);
			}
		}
	}

	/**
	 * 准备数据库
	 * 
	 * @throws IOException
	 */
	public void preDatasources() throws IOException {
		File f = new File(this.dsPath);
		FileReader fr = new FileReader(f);
		BufferedReader br = new BufferedReader(fr);
		String line = br.readLine();
		while (line != null) {
			if (!line.startsWith("#")) {
				String[] temp = line.split(",");
				if (temp.length == 11 && "12".contains(temp[10])) {
					DataSource ds = new DataSource();
					ds.setId(temp[0]);
					ds.setName(temp[1]);
					ds.setIp(temp[2]);
					ds.setDbport(temp[3]);
					ds.setDatabase(temp[4]);
					ds.setDbUsername(temp[5]);
					ds.setDbPassword(temp[6]);
					ds.setSshport(temp[7]);
					ds.setSshUsername(temp[8]);
					ds.setSshPassword(temp[9]);
					ds.setStatus(temp[10]);
					dsList.add(ds);
					writeTotalLog("发现有效数据源" + ds + ", 连接方式 : " + ds.getMethod(), null);
				}
			}
			line = br.readLine();
		}
		br.close();
		fr.close();
	}

	/**
	 * 一次性读入SQL脚本
	 * 
	 * @throws IOException
	 */
	public void preDDLSqls() throws IOException {
		for (int i = 0; i < files.size(); i++) {
			File f = new File(files.get(i));
			FileReader fr = new FileReader(f);
			BufferedReader br = new BufferedReader(fr);
			String line;
			StringBuffer sb = new StringBuffer();
			while ((line = br.readLine()) != null) {
				sb.append(line);
				sb.append("\n");
			}
			br.close();
			fr.close();
			ddlSql.put(f.getName(), sb.toString());
			writeTotalLog(f.getName() + " 缓存成功", null);
		}
	}

	/**
	 * 拼接异常信息
	 * 
	 * @param exception
	 * @return
	 */
	public static String pullException(Exception exception) {
		StringBuffer sb = new StringBuffer();
		sb.append("<p>").append(exception).append("</br></p>");
		StackTraceElement[] st = exception.getStackTrace();
		for (StackTraceElement t : st) {
			sb.append("<p class='errorClass'>at ").append(t.getClassName()).append(".").append(t.getMethodName());
			sb.append("(").append(t.getFileName()).append(":").append(t.getLineNumber()).append(")</br></p>");
		}
		return sb.toString();
	}

	/**
	 * 关闭文件流
	 * 
	 * @param fw
	 */
	public static void destory(FileWriter fw) {
		try {
			fw.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
